#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dbus/dbus.h>
#include <unistd.h>

#include <iostream>
#include <string>

#include "cJSON.h"


using namespace std;

char *getJsonStr(int count)
{
    char *pJsonStr = new char;
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    cJSON_AddStringToObject(root, "name", "AD");
    cJSON_AddNumberToObject(root, "age", count);

    pJsonStr = cJSON_Print(root);

    cJSON_Delete(root);

    return pJsonStr;
}



//建立与session D-Bus daemo的连接，并设定连接的名字，相关的代码已经多次使用过了
DBusConnection* connect_dbus()
{
    DBusError err;
    DBusConnection *connection;
    int ret;

    //Step 1: connecting session bus

    dbus_error_init(&err);

    connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr, "ConnectionErr : %s\n", err.message);
        dbus_error_free(&err);
    }
    if(connection == NULL)
    {
        printf("%d - error: %s\n", __LINE__, strerror(errno));
        return NULL;
    }

    //step 2: 设置BUS name，也即连接的名字。
    ret = dbus_bus_request_name(connection, "test.wei.sendSignal", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr, "Name Err :%s\n", err.message);
        dbus_error_free(&err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    {
        printf("%d - error: %s\n", __LINE__, strerror(errno));
        return NULL;
    }

    return connection;
}


// 发送信号
int send_signal(DBusConnection *connection, char *sigvalue)
{
    DBusMessage *msg;
    DBusMessageIter arg;
    dbus_uint32_t  serial = 0;          // 将答复与请求关联的唯一编号

    //步骤3:发送一个信号
    //根据图，我们给出这个信号的路径（即可以指向对象），接口，以及信号名，创建一个Message
    if((msg = dbus_message_new_signal("/test/signal/Object", "test.signal.Type", "Test"))== NULL)
    {
        fprintf(stderr, "Message NULL\n");
        return -1;
    }

    //给这个信号（messge）具体的内容 - 发送的类型是字符串类型
    dbus_message_iter_init_append(msg, &arg);
    if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue))
    {
        fprintf(stderr, "Out OfMemory!\n");
        return -1;
    }

    //步骤4: 将信号从连接中发送
    if(!dbus_connection_send(connection, msg, &serial)){
        fprintf(stderr, "Out of Memory!\n");
        return -1;
    }
    dbus_connection_flush(connection);
    printf("Signal Send Finish.\n");

    //步骤5: 释放相关的分配的内存。
    dbus_message_unref(msg);
    return 0;
}


int send_signal(DBusConnection *connection, int intVal)
{
    DBusMessage *msg;
    DBusMessageIter arg;
    dbus_uint32_t  serial = 0;          

    //步骤3:发送一个信号
    //根据图，我们给出这个信号的路径（即可以指向对象），接口，以及信号名，创建一个Message
    if((msg = dbus_message_new_signal("/test/signal/Object", "test.signal.Type", "Test"))== NULL)
    {
        fprintf(stderr, "Message NULL.\n");
        return -1;
    }
    //给这个信号（messge）具体的内容
    dbus_message_iter_init_append(msg, &arg);
    if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_UINT32, &intVal))
    {
        fprintf(stderr, "Out OfMemory!\n");
        return -1;
    }

    //步骤4: 将信号从连接中发送
    if(!dbus_connection_send(connection, msg, &serial))
    {
        fprintf(stderr, "Out of Memory!\n");
        return -1;
    }

    dbus_connection_flush(connection);

    printf("Signal Send Finish.\n");


    //步骤5: 释放相关的分配的内存。
    dbus_message_unref(msg);
    return 0;
}

struct Data {
    int value;
    std::string name;
};


int main()
{
    printf("================ Send Signal ===============\n");

    // 连接总线
    DBusConnection *pConnect = connect_dbus();
    if ( nullptr == pConnect )
    {
        printf("LINE: %d - %s\n", __LINE__, strerror(errno));
        return -1;
    }

    // 发送信号
    int count = 10;
    while(count--)
    {
        // 序列化数据，转换成通用的数据结构，以便其他应用使用
        char *point = getJsonStr(count);
        send_signal(pConnect, point);

        free(point);
        point = nullptr;

        usleep(10 * 1000);
    }

    printf("Send Signal Finish.\n");


    return 0;
}
